package com.hiof.moraa.server.service;

import com.hiof.moraa.server.service.model.CartesianCoordinate;
import com.hiof.moraa.server.service.model.GeoPoint;
import com.hiof.moraa.server.service.model.GoogleGpsGeoPoint;

/**
 * @author Bergy
 */
public class GeometryService {

    /**
     * Calculate the distance between two geometry points and return the
     * distance measured by km
     *
     * @param p1: geo point 1
     * @param p2: geo point 2
     * @return: distance by kilometers
     */
    public double distanceByKilometers(GeoPoint p1, GeoPoint p2) {
        double distanceByMeters = distanceByMeters(p1, p2);
        return convert2Kilometers(distanceByMeters);
    }

    /**
     * Calculate the time and its measure unit is minutes
     *
     * @param distance: meter
     * @param speed:    km/h
     * @return: minutes
     */
    public double predictTimeBySpeedAndDistance(double speed, double distance) {
        double distanceByKm = convert2Kilometers(distance);
        double timeByHours = distanceByKm / speed;
        return convert2Minutes(timeByHours);
    }

    /**
     * Calculate the time and its measure unit is minutes
     *
     * @param speed: km/h
     * @param p1:    geo point 1
     * @param p2:    geo point 2
     * @return : minutes
     */
    public double predictTimeBySpeedAndGeoPoints(double speed, GeoPoint p1, GeoPoint p2) {
        double distanceByMeters = distanceByMeters(p1, p2);
        return predictTimeBySpeedAndDistance(speed, distanceByMeters);
    }

    /**
     * Calculate the distance between two geometry points and return the
     * distance measured by km
     *
     * @param p1: geo point 1
     * @param p2: geo point 2
     * @return: distance by meters
     */
    public double distanceByMeters(GeoPoint p1, GeoPoint p2) {
        if (p1.getAltitude() != 0 && p2.getAltitude() != 0) {
            CartesianCoordinate c1 = p1.toCartersianCartesianCoordinate();
            CartesianCoordinate c2 = p2.toCartersianCartesianCoordinate();
            return CartesianCoordinate.distance(c1, c2);
        }else{
            GeoPoint alternativeP1 = new GoogleGpsGeoPoint(p1.getLat(), p1.getLng(), 0);
            GeoPoint alternativeP2 = new GoogleGpsGeoPoint(p2.getLat(), p2.getLng(), 0);
            CartesianCoordinate c1 = alternativeP1.toCartersianCartesianCoordinate();
            CartesianCoordinate c2 = alternativeP2.toCartersianCartesianCoordinate();
            return CartesianCoordinate.distance(c1, c2);
        }
    }

    private double convert2Kilometers(double meters) {
        return meters / 1000;
    }

    private double convert2Minutes(double timeByHours) {
        return timeByHours * 60;
    }
}
